﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ColladaDotNet.Geometry;
using Microsoft.DirectX;

namespace BakalarskaPraca.Generation.Helpers
{
    public class GeometryBoundingBox
    {
        public Vector3 MinVector;
        public Vector3 MaxVector;

        public GeometryBoundingBox(Geometry source)
        {
            this.MinVector.X = source.Vertices.Min(v => v.Positions[0].X);
            this.MinVector.Y = source.Vertices.Min(v => v.Positions[0].Y);
            this.MinVector.Z = source.Vertices.Min(v => v.Positions[0].Z);
            this.MaxVector.X = source.Vertices.Max(v => v.Positions[0].X);
            this.MaxVector.Y = source.Vertices.Max(v => v.Positions[0].Y);
            this.MaxVector.Z = source.Vertices.Max(v => v.Positions[0].Z);
        }

        public GeometryBoundingBox(List<Geometry> source)
        {
            List<GeometryBoundingBox> bboxes = new List<GeometryBoundingBox>();
            source.ForEach(g => bboxes.Add(new GeometryBoundingBox(g)));
            this.MinVector.X = bboxes.Min(v => v.MinVector.X);
            this.MinVector.Y = bboxes.Min(v => v.MinVector.Y);
            this.MinVector.Z = bboxes.Min(v => v.MinVector.Z);
            this.MaxVector.X = bboxes.Max(v => v.MaxVector.X);
            this.MaxVector.Y = bboxes.Max(v => v.MaxVector.Y);
            this.MaxVector.Z = bboxes.Max(v => v.MaxVector.Z);
        }

        public GeometryBoundingBox(List<Vector3> source)
        {
            this.MinVector.X = source.Min(v => v.X);
            this.MinVector.Y = source.Min(v => v.Y);
            this.MinVector.Z = source.Min(v => v.Z);
            this.MaxVector.X = source.Max(v => v.X);
            this.MaxVector.Y = source.Max(v => v.Y);
            this.MaxVector.Z = source.Max(v => v.Z);
        }

        private bool IntersectDimension(float min1,  float max1, float min2, float max2)
        {
            return MathHelper.InRange(min1, max1, min2) || MathHelper.InRange(min1, max1, max2) ||
                   MathHelper.InRange(min2, max2, min1) || MathHelper.InRange(min2, max2, max1);
        }

        public bool IsIntersecting(GeometryBoundingBox boundingBox)
        {
            return
                this.IntersectDimension(this.MinVector.X, this.MaxVector.X, boundingBox.MinVector.X,
                                        boundingBox.MaxVector.X) &&
                this.IntersectDimension(this.MinVector.Y, this.MaxVector.Y, boundingBox.MinVector.Y,
                                        boundingBox.MaxVector.Y) &&
                this.IntersectDimension(this.MinVector.Z, this.MaxVector.Z, boundingBox.MinVector.Z,
                                        boundingBox.MaxVector.Z);
        }

        public bool Contains(Vector3 point)
        {
            return MathHelper.InRange(this.MinVector.X, this.MaxVector.X, point.X) &&
                   MathHelper.InRange(this.MinVector.Y, this.MaxVector.Y, point.Y) &&
                   MathHelper.InRange(this.MinVector.Z, this.MaxVector.Z, point.Z);
        }
    }
}
